﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
using System.Xaml;
using System.Runtime.Serialization.Formatters.Binary;

using Prism.Games.GalEngine.Scripts;
using Prism.Core.Audio;

using Prism.Games.GalEngine.Scripts.Parser.Input;

namespace Prism.Games.GalEngine.Scripts.Parser
{
    public class ScriptParser
    {
        #region Properties and Fields

        public bool IsParsing { get; set; }

        public GraphicBase GraphicBase { get; set; }

        public AudioBase AudioManager { get; set; }

        public ReadonlyPacker Packer { get; set; }

        public SaveDataManager SaveDataManager { get; set; }

        public TierState TierState { get; set; }

        public bool IsSectionJump { get; set; }

        public bool IsNextSectionFromMenu { get; set; }

        public SecondTierGUIState SecondTierGUIState { get; set; }

        public PlayHelper PlayHelper { get; set; }

        public LogManager LogManager { get; set; }

        public BgmParser BgmParser { get; set; }

        public TrademarkBgmParser TrademarkBgmParser { get; set; }

        public BgiParser BgiParser { get; set; }

        public TrademarkBgiParser TrademarkBgiParser { get; set; }

        public EffectSoundParser ESParser { get; set; }

        public VIParser VIParser { get; set; }

        public EIParser EIParser { get; set; }

        public SystemSoundParser SystemSoundParser { get; set; }

        public VocalParser VocalParser { get; set; }

        public DialogueParser DialogueParser { get; set; }

        public TrademarkImageParser TrademarkImageParser { get; set; }

        public MenuBgmParser MenuBgmParser { get; set; }

        public MenuBgiParser MenuBgiParser { get; set; }

        public SelectorParser SelectorParser { get; set; }

        public SceneParserCollection SceneParsers { get; set; }

        public ParserState CurrentState { get; set; }

        public ParserState RunningPreState { get; set; }

        public GameConfig GameConfig { get; set; }

        public Queue<Cache> CacheQueue { get; set; }

        public MemoryDataStore MemoryDataStore { get; set; }

        protected object locker = new object();

        #endregion

        public ScriptParser(Script script)
        {
            this.GraphicBase = new GraphicBase();

            Helper.GraphicBase = this.GraphicBase;

            Helper.Script = script;

            this.CacheQueue = new Queue<Parser.Cache>();

            this.IsSectionJump = false;

            this.CurrentState = new ParserState();

            this.SceneParsers = new SceneParserCollection();

            // this.AudioManager = new AudioBase(script.GameName, script.Version);

            this.AudioManager = new AudioBase();

            Helper.AudioBase = this.AudioManager;

            this.BgiParser = new BgiParser();

            this.TrademarkBgiParser = new TrademarkBgiParser();

            this.BgmParser = new BgmParser();

            this.TrademarkBgmParser = new TrademarkBgmParser();

            this.ESParser = new EffectSoundParser();

            this.VIParser = new VIParser();

            this.DialogueParser = new DialogueParser();

            this.EIParser = new EIParser();

            this.VocalParser = new VocalParser();

            this.TrademarkImageParser = new TrademarkImageParser();

            this.MenuBgmParser = new MenuBgmParser();

            this.MenuBgiParser = new MenuBgiParser();

            this.SystemSoundParser = new SystemSoundParser();

            this.SelectorParser = new SelectorParser();

            this.SceneParsers.Add(this.BgiParser);
            this.SceneParsers.Add(this.TrademarkBgiParser);
            this.SceneParsers.Add(this.BgmParser);
            this.SceneParsers.Add(this.ESParser);
            this.SceneParsers.Add(this.VIParser);
            this.SceneParsers.Add(this.DialogueParser);
            this.SceneParsers.Add(this.EIParser);
            this.SceneParsers.Add(this.VocalParser);
            this.SceneParsers.Add(this.TrademarkImageParser);
            this.SceneParsers.Add(this.MenuBgmParser);
            this.SceneParsers.Add(this.MenuBgiParser);

            this.SceneParsers.Add(this.TrademarkBgmParser);
            this.SceneParsers.Add(this.SelectorParser);

            this.SaveDataManager = new SaveDataManager();

            this.LogManager = new LogManager(this);

            this.Packer = new ReadonlyPacker(GameFrameLibrary.Strings.ResourcePack);
            this.Packer.SetPackagePath(Path.GetFullPath(GameFrameLibrary.Strings.ResourcePack));

            Helper.Packer = this.Packer;

            this.PlayHelper = new PlayHelper(this);

            Helper.Parser = this;

            // SE。
            this.SystemSoundParser.LoadAllSE();

            this.MemoryDataStore = new MemoryDataStore();

            this.MemoryDataStore.OnStoreRoles(Helper.Script.Resource.Roles);

            Helper.MemoryDataStore = this.MemoryDataStore;
        }

        /// <summary>
        /// 初始化。
        /// </summary>
        public void Initialization()
        {
            this.MemoryDataStore.OnRoleReset(Helper.Script.Resource.Roles);

            this.RunningPreState = null;

            this.SecondTierGUIState = Parser.SecondTierGUIState.None;

            this.CurrentState.StateInit(Helper.Script);

            this.TierState = Parser.TierState.First;

            this.StartCurrent();
        }

        protected virtual bool OnStartCurrent()
        {
            // 运行在选项选择模式下，则不做任何动作。
            if (this.SelectorParser.IsInSelectorMode)
                return false;

            if (this.isMenuHide)
            {
                this.ShowMenu();
                return false;
            }

            // 运行在末尾处结束。
            if (this.CurrentState.IsEnd)
            {
                this.PlayHelper.StopAutoPlay();
                this.PlayHelper.StopSkipMode();

                this.Restart();
                return false;
            }

            if (this.CurrentState.Scene is TrademarkScene || this.CurrentState.Scene is VideoScene || this.CurrentState.Scene is MenuScene)
            {
                this.PlayHelper.StopAutoPlay();
                this.PlayHelper.StopSkipMode();
            }

            this.IsParsing = true;

            return true;
        }

        /// <summary>
        /// 最主要的脚本运行方法。
        /// </summary>
        public void StartCurrent()
        {
            if (this.OnStartCurrent() == false)
                return;

            this.SaveDataManager.SaveState = new ParserState();
            this.SaveDataManager.SaveState.Scene = this.CurrentState.Scene;
            this.SaveDataManager.SaveState.Section = this.CurrentState.Section;

            if (this.CurrentState.Section.Scenes.First().Id == this.CurrentState.Scene.Id)
            {
                this.CurrentState.SceneIsSectionHead = true;
            }
            else this.CurrentState.SceneIsSectionHead = false;

            #region Stop Audio
            if (this.CurrentState.Scene is TrademarkScene)
            {
                this.BgmParser.Restart();
                this.MenuBgmParser.Restart();
            }
            else if (this.CurrentState.Scene is MenuScene)
            {
                this.BgmParser.Restart();
            }
            else if (this.CurrentState.Scene is VideoScene)
            {
                this.MenuBgmParser.Restart();
                this.BgmParser.Restart();
            }
            else if (this.CurrentState.Scene is GamingScene)
            {
                this.MenuBgmParser.Restart();
            }
            #endregion

            this.DetectFadeOut();
        }

        private void HandleSectionChange()
        {
            var sectionChangedEventArgs = new SectionChangedEventArgs();

            if (this.CurrentState.SceneIsSectionHead)
            {
                if (Helper.Script.Sections.First().Id == this.CurrentState.Section.Id)
                {
                    if (this.RunningPreState != null)
                    {
                        sectionChangedEventArgs.OldSection = this.RunningPreState.Section;
                        this.MemoryDataStore.OnRoleReset(Helper.Script.Resource.Roles);
                    }

                    sectionChangedEventArgs.NewSection = this.CurrentState.Section;

                    this.OnSectionChanged(sectionChangedEventArgs, new Action(delegate()
                    {
                        this.StartPresentScene();
                        return;
                    }));
                    return;
                }
                else
                {
                    sectionChangedEventArgs.OldSection = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.RunningPreState.Section)];

                    sectionChangedEventArgs.NewSection = this.CurrentState.Section;

                    this.OnSectionChanged(sectionChangedEventArgs, new Action(delegate()
                    {
                        this.StartPresentScene();
                        return;
                    }));

                    return;
                }
            }
            else if (this.SaveDataManager.IsJustFromLoad)
            {
                this.SaveDataManager.IsJustFromLoad = false;

                sectionChangedEventArgs.OldSection = this.RunningPreState.Section;

                sectionChangedEventArgs.NewSection = this.CurrentState.Section;

                this.OnSectionChanged(sectionChangedEventArgs, new Action(delegate()
                {
                    this.StartPresentScene();
                    return;
                }));

                return;
            }
            else
            {
                this.StartPresentScene();
                return;
            }
        }

        private void DetectFadeOut()
        {
            var elementName = string.Empty;

            if (this.CurrentState.Scene is GamingScene && this.RunningPreState.Scene is GamingScene)
            {
                if (this.CurrentState.SceneIsSectionHead)
                    elementName = GameFrameLibrary.Strings.GameFrameFadeOut;
                else
                {
                    if (this.CurrentState.GamingScene.BackgroundImage.Id == this.RunningPreState.GamingScene.BackgroundImage.Id)
                        elementName = string.Empty;
                    else
                        elementName = GameFrameLibrary.Strings.GameFrameFadeOut;
                }
            }
            else if (this.CurrentState.Scene is GamingScene && this.RunningPreState.Scene is MenuScene)
            {
                elementName = GameFrameLibrary.Strings.MenuFadeOut;
            }

            if (elementName != string.Empty)
            {
                this.GraphicBase.PlayAnimation(elementName, new Action(delegate()
                {
                    this.GraphicBase.GameWindow.GetDispatcher().Invoke(new Action(delegate()
                    {
                        this.HandleSectionChange();
                        return;
                    }), null);
                    return;

                }));
                return;
            }
            else
            {
                this.HandleSectionChange();
            }
        }

        private void StartPresentScene()
        {
            #region TrademarkScene

            // 渲染场景
            if (this.CurrentState.Scene is TrademarkScene)
            {
                var scene = this.CurrentState.Scene as TrademarkScene;
                this.GraphicBase.SwicthFrame(scene);

                // TrademarkImage
                this.TrademarkImageParser.PresentObject(scene.TrademarkImage);

                // BackgroundImage
                this.TrademarkBgiParser.PresentObject(scene.BackgroundImage);

                // BackgroundMusic
                this.TrademarkBgmParser.PresentObject(scene.BackgroundMusic);

                this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.TrademarkFade, null);
                this.EndPresentScene();
                return;
            }
            #endregion

            #region MenuScene
            else if (this.CurrentState.Scene is MenuScene)
            {
                #region while menuScene reset cohesion
                foreach (var i in Helper.Script.Resource.Roles)
                {
                    i.Cohesion = 0;
                }
                #endregion

                var scene = this.CurrentState.Scene as MenuScene;
                this.GraphicBase.SwicthFrame(scene);

                // BackgroundImage
                this.MenuBgiParser.PresentObject(scene.BackgroundImage);

                // Bgm
                this.MenuBgmParser.PresentObject(scene.BackgroundMusic);

                this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.MenuFadeIn, null);

                this.IsNextSectionFromMenu = true;
                this.EndPresentScene();
                return;
            }
            #endregion

            #region VideoScene
            else if (this.CurrentState.Scene is VideoScene)
            {
                var scene = this.CurrentState.Scene as VideoScene;
                this.GraphicBase.SwicthFrame(scene);

                if (scene.Video.PartUri != null)
                {
                    var tempPath = Path.GetFullPath(GameFrameLibrary.Strings.Temp + scene.Video.PartUri.OriginalString);

                    this.Packer.SavePartAsFile(scene.Video.PartUri, tempPath);

                    var mediaElement = this.GraphicBase.GameWindow.FindName(GameFrameLibrary.Strings.VideoMediaElement) as System.Windows.Controls.MediaElement;
                    mediaElement.Source = new Uri(tempPath, UriKind.RelativeOrAbsolute);
                }

                this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.VideoFadeIn, null);
                this.EndPresentScene();
                return;

            }
            #endregion

            #region GamingScene
            else if (this.CurrentState.Scene is GamingScene)
            {
                var scene = this.CurrentState.Scene as GamingScene;
                this.GraphicBase.SwicthFrame(scene);
                this.PresentGamingScene(scene);
                this.EndPresentScene();
                return;
            }

            #endregion
        }

        private void EndPresentScene()
        {
            // 将该场景标记为已读。
            this.SetSceneIsRead(this.CurrentState.Scene as Prism.Games.GalEngine.Scripts.FunctionModel.IReaderLogable);

            if (this.CurrentState.Section.Branch != null)
            {
                if (!this.SelectorParser.IsInSelectorMode)
                {
                    if (this.CurrentState.Section.Scenes.Last().Id == this.CurrentState.Scene.Id)
                    {
                        this.BranchLeadingOutNextState();
                    }
                    else
                        this.DefaultLeadingOutNextState();
                }
            }
            else this.DefaultLeadingOutNextState();
        }

        private void SetSceneIsRead(Prism.Games.GalEngine.Scripts.FunctionModel.IReaderLogable xscene)
        {
            xscene.IsRead = true;
        }

        public void InSelectorModeStateNext()
        {
            if (this.RunningPreState.Section.Scenes.Last().Id == this.RunningPreState.Scene.Id)
            {
                this.BranchLeadingOutNextState();
            }
            else
                this.DefaultLeadingOutNextState();
        }

        private void PresentGamingScene(GamingScene scene)
        {
            // Bgi
            this.BgiParser.PresentObject(scene.BackgroundImage);

            // Bgm
            this.BgmParser.PresentObject(scene.BackgroundMusic);

            // VI
            this.VIParser.VICanvas.Children.Clear();

            foreach (var i in scene.VerticalImages)
            {
                this.VIParser.PresentObject(i);
            }

            // EI
            this.EIParser.PresentObject(scene.ExpressionImage);


            #region 检测背景是否切换，切换则FadeIn。
            if (this.BgiParser.preBgi == null)
            {
                this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.GamingFrameFadeIn, null);
            }
            else
            {
                if (this.IsSectionJump)
                {
                    this.IsSectionJump = false;
                    this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.GamingFrameFadeIn, null);
                }

                else if (this.BgiParser.preBgi.Id != -1)
                {
                    if (scene.BackgroundImage.Id != this.BgiParser.preBgi.Id)
                    {
                        this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.GamingFrameFadeIn, null);
                    }
                    else if (this.CurrentState.SceneIsSectionHead)
                    {
                        this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.GamingFrameFadeIn, null);
                    }
                }
                else
                    this.GraphicBase.PlayAnimation(GameFrameLibrary.Strings.GamingFrameFadeIn, null);
            }

            this.BgiParser.preBgi = scene.BackgroundImage;
            #endregion

            // Selector
            this.SelectorParser.PresentObject(scene.Selector);

            // Dialogue and Role
            this.DialogueParser.PresentObject(scene.Dialogue, scene.Role);

            // ES
            this.ESParser.PresentObject(scene.SystemSound);

            // Vocal
            this.VocalParser.PresentObject(scene.Vocal);
        }

        /// <summary>
        /// 无分支情况下，按照默认的顺序渲染。
        /// </summary>
        private void DefaultLeadingOutNextState()
        {
            this.OnRunningPreStateChanged();

            // 渲染完毕，推进下一场景。
            if (this.CurrentState.Scene.Id != this.CurrentState.Section.Scenes.Last().Id)
            {
                this.CurrentState.Scene = this.CurrentState.Section.Scenes[this.CurrentState.Section.Scenes.IndexOf(this.CurrentState.Scene) + 1];
            }
            else
            {
                if (this.CurrentState.Section.Id != Helper.Script.Sections.Last().Id)
                {
                    var x = 0;
                    do
                    {
                        x++;
                    }
                    while (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count == 0);

                    if (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count != 0)
                    {
                        this.CurrentState.Section = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x];
                    }
                    this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];

                    this.IsSectionJump = true;
                }
                else
                {
                    // 运行在末尾处结束。
                    if (this.CurrentState.Scene.Id == Helper.Script.Sections.Last().Scenes.Last().Id)
                    {
                        this.CurrentState.IsEnd = true;
                    }
                }
            }
            this.OnEndCurrent();
        }

        /// <summary>
        /// 有分支情况下，按照分支设定进行判定。
        /// </summary>
        private void BranchLeadingOutNextState()
        {
            this.OnRunningPreStateChanged();

            var branch = this.CurrentState.Section.Branch;
            if (branch == null)
                return;
            foreach (var i in branch.SectionJumpers)
            {
                var conditionCount = i.Conditions.Count;
                var conditionCounter = 0;
                var isEnableCounterMode = false;

                #region Conditions
                foreach (var j in i.Conditions)
                {
                    var q = from role in Helper.Script.Resource.Roles
                            where role.Id == j.Role
                            select role;
                    if (q.Count() == 1)
                    {
                        var role = q.Single();
                        if (j.ConditionOperator == Data.BranchSystem.ConditionOperator.Equal)
                        {
                            if (j.Value == role.Cohesion)
                            {
                                if (i.ConditionJudgMode == Data.BranchSystem.ConditionJudgMode.JustOneCorrect)
                                {
                                    var q2 = from section in Helper.Script.Sections
                                             where section.Id == i.TargetSection
                                             select section;
                                    if (q2.Count() == 1)
                                    {
                                        this.CurrentState.Section = q2.Single();
                                        if (this.CurrentState.Section.Scenes.Count == 0)
                                        {
                                            var x = 0;
                                            do
                                            {
                                                x++;
                                            }
                                            while (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count == 0);

                                            if (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count != 0)
                                            {
                                                this.CurrentState.Section = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x];
                                            }
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        else
                                        {
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        this.IsSectionJump = true;
                                    }
                                }
                                else
                                {
                                    isEnableCounterMode = true;
                                    conditionCounter++;
                                }
                            }
                            else this.DefaultLeadingOutNextState();
                        }
                        else if (j.ConditionOperator == Data.BranchSystem.ConditionOperator.GreaterThan)
                        {
                            if (role.Cohesion > j.Value)
                            {
                                if (i.ConditionJudgMode == Data.BranchSystem.ConditionJudgMode.JustOneCorrect)
                                {
                                    var q2 = from section in Helper.Script.Sections
                                             where section.Id == i.TargetSection
                                             select section;
                                    if (q2.Count() == 1)
                                    {
                                        this.CurrentState.Section = q2.Single();
                                        if (this.CurrentState.Section.Scenes.Count == 0)
                                        {
                                            var x = 0;
                                            do
                                            {
                                                x++;
                                            }
                                            while (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count == 0);

                                            if (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count != 0)
                                            {
                                                this.CurrentState.Section = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x];
                                            }
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        else
                                        {
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        this.IsSectionJump = true;
                                    }
                                }
                                else
                                {
                                    isEnableCounterMode = true;
                                    conditionCounter++;
                                }
                            }
                            else this.DefaultLeadingOutNextState();
                        }
                        else if (j.ConditionOperator == Data.BranchSystem.ConditionOperator.LessThan)
                        {
                            if (role.Cohesion < j.Value)
                            {
                                if (i.ConditionJudgMode == Data.BranchSystem.ConditionJudgMode.JustOneCorrect)
                                {
                                    var q2 = from section in Helper.Script.Sections
                                             where section.Id == i.TargetSection
                                             select section;
                                    if (q2.Count() == 1)
                                    {
                                        this.CurrentState.Section = q2.Single();
                                        if (this.CurrentState.Section.Scenes.Count == 0)
                                        {
                                            var x = 0;
                                            do
                                            {
                                                x++;
                                            }
                                            while (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count == 0);

                                            if (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count != 0)
                                            {
                                                this.CurrentState.Section = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x];
                                            }
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        else
                                        {
                                            this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                                        }
                                        this.IsSectionJump = true;
                                    }
                                }
                                else
                                {
                                    isEnableCounterMode = true;
                                    conditionCounter++;
                                }
                            }
                            else this.DefaultLeadingOutNextState();
                        }
                    }
                }
                #endregion

                if (isEnableCounterMode)
                {
                    isEnableCounterMode = false;
                    if (conditionCounter == conditionCount)
                    {
                        var q3 = from section in Helper.Script.Sections
                                 where section.Id == i.TargetSection
                                 select section;
                        if (q3.Count() == 1)
                        {
                            this.CurrentState.Section = q3.Single();
                            if (this.CurrentState.Section.Scenes.Count == 0)
                            {
                                var x = 0;
                                do
                                {
                                    x++;
                                }
                                while (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count == 0);

                                if (Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x].Scenes.Count != 0)
                                {
                                    this.CurrentState.Section = Helper.Script.Sections[Helper.Script.Sections.IndexOf(this.CurrentState.Section) + x];
                                }
                                this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                            }
                            else
                            {
                                this.CurrentState.Scene = this.CurrentState.Section.Scenes[0];
                            }
                            this.IsSectionJump = true;
                        }
                    }
                    else this.DefaultLeadingOutNextState();
                }
            }
            this.OnEndCurrent();
        }

        /// <summary>
        /// 当前一个State参数被替换。
        /// </summary>
        private void OnRunningPreStateChanged()
        {
            this.RunningPreState = new ParserState();
            this.RunningPreState.Scene = this.CurrentState.Scene;
            this.RunningPreState.Section = this.CurrentState.Section;
            this.RunningPreState.SceneIsSectionHead = this.CurrentState.SceneIsSectionHead;
            this.RunningPreState.GamingScene = this.CurrentState.GamingScene;
            this.RunningPreState.IsEnd = this.CurrentState.IsEnd;
            this.RunningPreState.RunningMode = this.CurrentState.RunningMode;
        }

        /// <summary>
        /// 完成当前。
        /// </summary>
        protected virtual void OnEndCurrent()
        {
            this.IsParsing = false;
        }

        public virtual void OnSectionChanged(SectionChangedEventArgs e)
        {
            if (e.OldSection != null)
            {
                foreach (var i in e.OldSection.Scenes)
                {
                    if (this.CacheQueue.Count == 1)
                    {
                        var cache = this.CacheQueue.Dequeue();
                        cache.Clear();
                    }
                }
            }

            if (e.NewSection != null)
            {
                var cache = new Cache();
                Helper.CurrentCache = cache;
                foreach (var i in e.NewSection.Scenes)
                {
                    ResourcePreLoader.CacheScene(i);
                }
                this.CacheQueue.Enqueue(cache);
            }
        }

        public virtual void OnSectionChanged(SectionChangedEventArgs e, Action sectionChangedCallback)
        {
            Helper.GraphicBase.ShowLoadingFrame(new Action(delegate()
            {
                if (e.OldSection != null)
                {
                    foreach (var i in e.OldSection.Scenes)
                    {
                        if (this.CacheQueue.Count == 1)
                        {
                            var cache = this.CacheQueue.Dequeue();
                            cache.Clear();
                        }
                    }
                }

                if (e.NewSection != null)
                {
                    var cache = new Cache();
                    Helper.CurrentCache = cache;
                    foreach (var i in e.NewSection.Scenes)
                    {
                        ResourcePreLoader.CacheScene(i);
                    }
                    this.CacheQueue.Enqueue(cache);
                }
            }), sectionChangedCallback);
        }

        /// <summary>
        /// 结束运行。
        /// </summary>
        public void End()
        {
            this.ShowMessageBanner(GameFrameLibrary.Strings.ExitTip, new Action(delegate()
                {
                    this.GraphicBase.GameWindow.CloseFromParser = true;

                    this.GraphicBase.PlayMainAnimation(GameFrameLibrary.Strings.MainFadeOut, new Action(delegate()
                    {
                        this.SceneParsers.RestartAllParser();

                        this.MemoryDataStore.OnRoleReset(Helper.Script.Resource.Roles);

                        this.SaveDataManager.SaveSystemData();

                        this.GraphicBase.GameWindow.SaveWindowConfig();

                        var dirInfo = new DirectoryInfo(GameFrameLibrary.Strings.Temp);

                        dirInfo.DeleteFolderAllContent();

                        this.GraphicBase.CloseGalWindow();
                    }));
                }));
        }

        /// <summary>
        /// 重新运行。
        /// </summary>
        public void Restart()
        {
            this.ShowMessageBanner(GameFrameLibrary.Strings.ReturnTitleTip, new Action(delegate()
                {
                    this.OnSectionChanged(new SectionChangedEventArgs() { OldSection = this.RunningPreState.Section });

                    this.IsSectionJump = false;

                    this.GraphicBase.GameWindow.SetContent(null);

                    this.GraphicBase.GameWindow.SetSecondContent(null);

                    this.GraphicBase.GameWindow.SetThirdContent(null);

                    this.SceneParsers.RestartAllParser();

                    this.Initialization();
                }));
        }

        #region SecondTier Flip

        public void DeleteSecondContent()
        {
            if (this.TierState.HasFlag(TierState.Second))
            {
                var anime = "";

                if (this.SecondTierGUIState == Parser.SecondTierGUIState.Load)
                {
                    anime = GameFrameLibrary.Strings.LoadFadeOut;
                }
                else if (this.SecondTierGUIState == Parser.SecondTierGUIState.Save)
                {
                    anime = GameFrameLibrary.Strings.SaveFadeOut;
                }
                else if (this.SecondTierGUIState == Parser.SecondTierGUIState.Config)
                {
                    anime = GameFrameLibrary.Strings.ConfigFadeOut;
                    this.GraphicBase.GameWindow.SaveWindowConfig();
                }
                else if (this.SecondTierGUIState == Parser.SecondTierGUIState.Log)
                {
                    anime = GameFrameLibrary.Strings.LogFadeOut;
                }

                this.GraphicBase.PlaySecondAnimation(anime, new Action(delegate()
                {
                    this.GraphicBase.GameWindow.SetSecondContent(null);
                    this.TierState &= Parser.TierState.Second;
                    this.SecondTierGUIState = Parser.SecondTierGUIState.None;
                }));
            }

        }

        /// <summary>
        /// 进入设定界面。
        /// </summary>
        public void EnterConfigGUI()
        {
            this.ShowMessageBanner(GameFrameLibrary.Strings.EnterConfigTip, new Action(delegate()
            {
                this.GraphicBase.GameWindow.SetSecondContent(this.GraphicBase.GalUIFrame.ConfigFrame);
                this.GraphicBase.PlaySecondAnimation(GameFrameLibrary.Strings.ConfigFadeIn, new Action(delegate()
                {
                    //Set config data...

                    this.TierState |= Parser.TierState.Second;

                    this.SecondTierGUIState = Parser.SecondTierGUIState.Config;
                }));
            }));
        }

        /// <summary>
        /// 进入存档加载器界面。
        /// </summary>
        public void EnterSaveDataLoaderGUI()
        {
            this.ShowMessageBanner(GameFrameLibrary.Strings.EnterLoadGUITip, new Action(delegate()
            {
                this.GraphicBase.GameWindow.SetSecondContent(this.GraphicBase.GalUIFrame.LoadFrame);
                var dataBox = this.GraphicBase.GameWindow.FindSecondName(GameFrameLibrary.Strings.LoadDataListBox) as GameFrameLibrary.DataBox;
                dataBox.DistributeElement(this.SaveDataManager.Datas);

                this.GraphicBase.PlaySecondAnimation(GameFrameLibrary.Strings.LoadFadeIn, null);
                this.TierState |= Parser.TierState.Second;
                this.SecondTierGUIState = Parser.SecondTierGUIState.Load;

            }));


        }

        /// <summary>
        /// 进入存档保存器界面。
        /// </summary>
        public void EnterSaveDataSaverGUI()
        {
            // 对游戏界面截图。
            var element = (FrameworkElement)((FrameworkElement)Helper.GraphicBase.GameWindow.GetContent()).FindName(GameFrameLibrary.Strings.BackgroundLayout);

            this.SaveDataManager.TakeShotCut(element);

            this.ShowMessageBanner(GameFrameLibrary.Strings.EnterSaveGUITip, new Action(delegate()
            {
                this.GraphicBase.GameWindow.SetSecondContent(this.GraphicBase.GalUIFrame.SaveFrame);
                var dataBox = this.GraphicBase.GameWindow.FindSecondName(GameFrameLibrary.Strings.SaveDataListBox) as GameFrameLibrary.DataBox;
                dataBox.DistributeElement(this.SaveDataManager.Datas);

                this.GraphicBase.PlaySecondAnimation(GameFrameLibrary.Strings.SaveFadeIn, null);
                this.TierState |= Parser.TierState.Second;
                this.SecondTierGUIState = Parser.SecondTierGUIState.Save;
            }));
        }

        #endregion

        #region Save and Load

        public void SaveData(object saveData)
        {
            var data = saveData as IPostionMarked;
            if (data == null)
                return;
            var savedData = this.SaveDataManager.Save(data.Postion);
            this.SaveDataManager.AddData(savedData);
            var dataBox = this.GraphicBase.GameWindow.FindSecondName(GameFrameLibrary.Strings.SaveDataListBox) as GameFrameLibrary.DataBox;
            dataBox.DistributeElement(this.SaveDataManager.Datas);

            // Save Datas to SaveDate Folder.
            var folder = GameFrameLibrary.Strings.SaveFolder;
            if (!System.IO.Directory.Exists(folder))
                System.IO.Directory.CreateDirectory(folder);

            var path = Path.Combine(folder, savedData.Postion.ToString() + "  " + savedData.State.GamingScene.Name + ".data");
            var bf = new BinaryFormatter();
            using (var fs = new FileStream(path, FileMode.Create))
            {
                bf.Serialize(fs, savedData);
            }
        }

        public void LoadData(object saveData)
        {
            var data = saveData as GalSaveData;
            if (data == null)
                return;

            this.IsSectionJump = false;

            this.GraphicBase.GameWindow.SetSecondContent(null);

            this.GraphicBase.GameWindow.SetThirdContent(null);

            this.SceneParsers.RestartAllParser();

            this.SaveDataManager.Load(data);
        }

        #endregion

        #region Hide Gaming Menu Parts.
        protected bool isMenuHide = false;
        public void HideMenu()
        {
            var content = (FrameworkElement)((FrameworkElement)Helper.GraphicBase.GameWindow.GetContent()).FindName("MenuLayout");
            content.Opacity = 0;
            this.isMenuHide = true;
        }
        public void ShowMenu()
        {
            var content = (FrameworkElement)((FrameworkElement)Helper.GraphicBase.GameWindow.GetContent()).FindName("MenuLayout");
            content.Opacity = 1;
            this.isMenuHide = false;
        }
        #endregion

        #region MessageBanner

        public void ShowMessageBanner(string message, Action bannerOKCallback)
        {
            this.GraphicBase.GameWindow.SetThirdContent(this.GraphicBase.GalUIFrame.MessageBannerFrame);
            var textBlock = this.GraphicBase.GameWindow.FindThirdName(GameFrameLibrary.Strings.MessageTextBlock) as TextBlock;
            textBlock.Text = message;

            this.TierState |= Parser.TierState.Third;

            this.MessageBannerOKCallback = bannerOKCallback;
            this.GraphicBase.PlayThirdAnimation(GameFrameLibrary.Strings.BannerFadeIn, null);
        }

        public void MessageBannerOK(bool result)
        {
            this.HideMessageBanner();
            if (result)
            {
                this.MessageBannerOKCallback();
            }
            else
            {
                this.GraphicBase.GameWindow.IsClosing = false;
            }
        }

        public Action MessageBannerOKCallback;

        public void HideMessageBanner()
        {
            this.GraphicBase.PlayThirdAnimation(GameFrameLibrary.Strings.BannerFadeOut, null);
            this.TierState ^= Parser.TierState.Third;
            this.GraphicBase.GameWindow.SetThirdContent(null);
        }

        #endregion
    }
}
